<template>
  <view class="da-tree" :style="{'--theme-color': themeColor}">
    <scroll-view class="da-tree-scroll" :scroll-y="true" :scroll-x="false">
      <view
        class="da-tree-item"
        :class="{'is-show': item.show}"
        :style="{paddingLeft: item.level * indent + 'rpx'}"
        v-for="item in datalist"
        :key="item.key">
        <view
          v-if="item.showArrow && !filterValue"
          class="da-tree-item__icon"
          @click="handleExpandedChange(item)">
          <view :class="['da-tree-item__icon--arr','is-loading']" v-if="loadLoading && item.loading"></view>
          <view :class="['da-tree-item__icon--arr','is-expand', {'is-right':!item.expand}]" v-else></view>
        </view>
        <view v-else class="da-tree-item__icon"></view>
        <view
          class="da-tree-item__checkbox"
          :class="[`da-tree-item__checkbox--${checkboxPlacement}`,{'is--disabled': item.disabled}]"
          v-if="showCheckbox"
          @click="handleCheckChange(item)">
          <view class="da-tree-item__checkbox--icon da-tree-checkbox-checked" v-if="item.checkedStatus === isCheckedStatus"></view>
          <view class="da-tree-item__checkbox--icon da-tree-checkbox-indeterminate" v-else-if="item.checkedStatus === halfCheckedStatus"></view>
          <view class="da-tree-item__checkbox--icon da-tree-checkbox-outline" v-else></view>
        </view>
        <view
          class="da-tree-item__checkbox"
          :class="[`da-tree-item__checkbox--${checkboxPlacement}`,{'is--disabled': item.disabled}]"
          v-if="!showCheckbox && showRadioIcon"
          @click="handleRadioChange(item)">
          <view class="da-tree-item__checkbox--icon da-tree-radio-checked" v-if="item.checkedStatus === isCheckedStatus"></view>
          <view class="da-tree-item__checkbox--icon da-tree-radio-indeterminate" v-else-if="item.checkedStatus === halfCheckedStatus"></view>
          <view class="da-tree-item__checkbox--icon da-tree-radio-outline" v-else></view>
        </view>
        <view class="da-tree-item__label" :class="'da-tree-item__label--'+item.checkedStatus" @click="handleLabelClick(item)">{{ item.label }} <text class="da-tree-item__label--append" v-if="item.append">{{ item.append }}</text></view>
      </view>
    </scroll-view>
  </view>
</template>

<script>

import { defineComponent, ref, unref, watch } from 'vue'

import {
  unCheckedStatus,
  halfCheckedStatus,
  isCheckedStatus,
  deepClone,
  getAllNodeKeys,
  getAllNodes,
  logError,
  isArray,
  isString,
  isNumber,
  isFunction,
} from './utils'
import basicProps from './props'

export default defineComponent({
  name: 'DaTree',
  props: basicProps,
  emits: ['change', 'expand'],
  setup(props, { emit }) {
    /** 原始的树数据 */
    const dataRef = ref([])
    /** 处理后的一维树项数据 */
    const datalist = ref([])
    /** 处理后的以key为键值的树项数据 */
    const datamap = ref({})
    /** 默认的展开数据 */
    const expandedKeys = ref([])
    /** 默认的已选数据 */
    const checkedKeys = ref(null)
    /** 加载状态 */
    const loadLoading = ref(false)
    let fieldMap = {
      value: 'value',
      label: 'label',
      children: 'children',
      disabled: 'disabled',
      append: 'append',
      leaf: 'leaf',
      sort: 'sort',
    }

    /**
     * 初始化数据结构
     */
    function initData() {
      fieldMap = {
        value: props.field?.key || props.field?.value || props.valueField || 'value',
        label: props.field?.label || props.labelField || 'label',
        children: props.field?.children || props.childrenField || 'children',
        disabled: props.field?.disabled || props.disabledField || 'disabled',
        append: props.field?.append || props.appendField || 'append',
        leaf: props.field?.leaf || props.leafField || 'leaf',
        sort: props.field?.sort || props.sortField || 'sort',
      }

      const data = deepClone(dataRef.value)
      datalist.value = []
      datamap.value = {}

      // clean tree
      handleTreeData(data)
      // flat tree
      datalist.value = checkInitData(datalist.value)
      // console.log('init datalist', datalist.value)
      // console.log('init datamap', datamap.value)
    }

    /**
     * 转换为节点数据
     * @param data
     * @param parent
     * @param level
     */
    function handleTreeData(data = [], parent = null, level = 0, insertIndex = -1) {
      return data.reduce((prev, cur, index) => {
        const key = cur[fieldMap.value]
        const children = cur[fieldMap.children] || null
        const newItem = createNewItem(cur, index, parent, level)
        if (insertIndex > -1) {
          // 插入子项尾部
          const index = (parent.childrenKeys?.length || 0) + insertIndex + 1
          if (!parent?.childrenKeys?.includes(key)) {
            datamap.value[key] = newItem
            datalist.value.splice(index, 0, newItem)
            parent.children.push(newItem)
            if (newItem.parentKeys?.length) {
              newItem.parentKeys.forEach(k => {
                datamap.value[k].childrenKeys = [...datamap.value[k].childrenKeys, newItem.key]
              })
            }
          }
        } else {
          datamap.value[key] = newItem
          datalist.value.push(newItem)
        }

        const hasChildren = children && children.length > 0
        if (hasChildren) {
          const childrenData = handleTreeData(children, newItem, level + 1)
          // childrenData.sort((a, b) => a.sort - b.sort)
          newItem.children = childrenData
          const childrenKeys = childrenData.reduce((p, k) => {
            const keys = k.childrenKeys
            p.push(...keys, k.key)
            return p
          }, [])
          newItem.childrenKeys = childrenKeys
        }
        prev.push(newItem)
        return prev
      }, [])
    }

    /**
     * 创建节点
     * @param item
     * @param index
     * @param parent
     * @param level
     */
    function createNewItem(item, index, parent, level) {
      const key = item[fieldMap.value]
      const label = item[fieldMap.label]
      const sort = item[fieldMap.sort] || 0
      const children = item[fieldMap.children] || null
      const append = item[fieldMap.append] || null
      let disabled = item[fieldMap.disabled] || false
      // 优先继承父级禁用属性
      disabled = parent?.disabled || disabled
      let isLeaf = isFunction(props.isLeafFn) ? props.isLeafFn(item) : (item[fieldMap.leaf] || false)
      // const hasChildren = children && children.length > 0
      const isEmptyChildren = children && children.length === 0
      let showArrow = true
      // let isLeaf = !hasChildren
      let expand = props.defaultExpandAll || false
      // 是否异步加载模式
      const isLoadMode = props.loadMode && isFunction(props.loadApi)

      if (!children) {
        expand = false
        if (isLoadMode) {
          showArrow = true
        } else {
          isLeaf = true
          showArrow = false
        }
      }

      if (isEmptyChildren) {
        expand = false
        if (isLoadMode) {
          showArrow = true
        } else {
          isLeaf = true
          showArrow = false
        }
      }

      if (isLeaf) {
        showArrow = false
        expand = false
      } else {
        showArrow = true
      }

      // onlyRadioLeaf 单选只能选择末级节点
      if (!props.showCheckbox) {
        if (props.onlyRadioLeaf) {
          if (!isLeaf) {
            disabled = true
          } else {
            // 仍旧继承父类原始禁用状态
            disabled = parent?.originItem?.disabled || false
          }
        }
      }

      if (disabled) {
        if (isLeaf || !children || isEmptyChildren) {
          expand = false
          showArrow = false
        }
      }

      const parentKey = parent ? parent.key : null
      const show = props.defaultExpandAll || level === 0

      const newItem = {
        key,
        parentKey,
        label,
        append,
        isLeaf,
        showArrow,
        level,
        expand,
        show,
        sort,
        disabled,
        loaded: false,
        loading: false,
        indexs: [index],
        checkedStatus: unCheckedStatus,
        parentKeys: [],
        childrenKeys: [],
        children: [],
        originItem: item,
      }

      if (parent) {
        newItem.parentKeys = [parent.key, ...parent.parentKeys]
        newItem.indexs = [...parent.indexs, index]
      }

      return newItem
    }

    /**
     * 处理初始化内容
     * @param list
     */
    function checkInitData(list) {
      let checkedKeyList = null
      let expandedKeyList = []
      if (props.showCheckbox) {
        checkedKeyList = [...new Set(checkedKeys.value || [])]
        expandedKeyList = props.expandChecked ? ([...(checkedKeys.value || []), ...(expandedKeys.value || [])]) : expandedKeys.value
      } else {
        checkedKeyList = checkedKeys.value || null
        expandedKeyList = props.expandChecked && checkedKeys.value ? ([checkedKeys.value, ...(expandedKeys.value || [])]) : expandedKeys.value
      }

      handleCheckState(list, checkedKeyList, true)

      // 处理初始展开
      expandedKeyList = [...new Set(expandedKeyList)]
      if (!props.defaultExpandAll) {
        handleExpandState(list, expandedKeyList, true)
      }

      list.sort((a, b) => {
        if (a.sort === 0 && b.sort === 0) {
          return 0
        }

        if (a.parentKey === b.parentKey) {
          if (a.sort - b.sort > 0) {
            return 1
          } else {
            return -1
          }
        }

        return 0
      })

      return list
    }

    /**
     * 处理选中
     * @param list
     * @param checkedKeyList
     */
    function handleCheckState(list, checkedKeyList, checked = true) {
      // 多选
      if (props.showCheckbox) {
        if (checkedKeyList?.length) {
          checkedKeyList.forEach(k => {
            const item = datamap.value[k]
            if (item) {
              checkTheChecked(item, checked)
            }
          })
        }

        return
      }

      // 单选
      for (let i = 0; i < list.length; i++) {
        const item = list[i]
        if (item.key === checkedKeyList) {
          checkTheRadio(item, checked)
          break
        }
      }
    }

    /**
     * 校验多选节点
     * @param item
     * @param checked
     */
    function checkTheChecked(item, checked = true) {
      const { childrenKeys, parentKeys, disabled = false } = item
      if (!props.checkedDisabled && disabled) return

      // 当前
      item.checkedStatus = checked ? isCheckedStatus : unCheckedStatus

      if (!props.checkStrictly) {
        // 子类
        childrenKeys.forEach(k => {
          const childrenItem = unref(datamap)[k]
          childrenItem.checkedStatus = (!props.checkedDisabled && childrenItem.disabled) ? childrenItem.checkedStatus : item.checkedStatus
        })

        // 父类
        parentKeys.forEach(k => {
          const parentItem = datamap.value[k]
          parentItem.checkedStatus = getParentCheckedStatus(parentItem)
        })
      }
    }

    /**
     * 校验单选节点
     * @param item
     */
    function checkTheRadio(item, checked) {
      const { parentKeys, isLeaf, disabled = false } = item
      if (!props.checkedDisabled && disabled) return

      // 限制末节点选中，但当前非末节点
      if (props.onlyRadioLeaf && !isLeaf) {
        logError(`限制了末节点选中，当前[${item.label}]非末节点`)
        return
      }

      if (datalist.value?.length) {
        datalist.value.forEach(k => {
          k.checkedStatus = unCheckedStatus
        })
      }

      parentKeys.forEach(k => {
        const parentItem = datamap.value[k]
        parentItem.checkedStatus = checked ? getParentCheckedStatus(parentItem) : unCheckedStatus
      })

      // 当前
      item.checkedStatus = checked ? isCheckedStatus : unCheckedStatus
    }

    /**
     * 处理父节点展开
     * @param item
     * @param expand
     */
    // function handleExpandParentNode(item, expand = true) {
    //   if (!expand) return

    //   if (item?.parentKeys?.length) {
    //     item.parentKeys.forEach(pk => {
    //       if (!datamap.value[pk].expand) {
    //         datamap.value[pk].expand = true
    //       }
    //     })
    //   }
    // }

    /**
     * 处理节点展开
     * @param list
     * @param expandedKeyList
     * @param expand
     */
    function handleExpandState(list, expandedKeyList, expand = true) {
      // 收起
      if (expand === false) {
        for (let i = 0; i < list.length; i++) {
          const item = list[i]
          if (expandedKeyList?.includes(item.key)) {
            item.expand = false
            if (item.childrenKeys?.length) {
              item.childrenKeys.forEach(ck => {
                datamap.value[ck].expand = false
                datamap.value[ck].show = false
              })
            }
          }
        }
        return
      }
      // 展开
      for (let i = 0; i < list.length; i++) {
        const item = list[i]
        // 处理展开
        if (expandedKeyList?.includes(item.key)) {
          // 父子
          item.expand = true
          if (item.children?.length) {
            item.children.forEach(k => {
              const kItem = unref(datamap)[k.key]
              kItem.show = true
            })
          }

          // 族系
          if (item.parentKeys?.length) {
            item.parentKeys.forEach(k => {
              const kItem = unref(datamap)[k]
              kItem.expand = true
              if (kItem.children?.length) {
                kItem.children.forEach(k => {
                  const skItem = unref(datamap)[k.key]
                  skItem.show = true
                })
              }
            })
          }
        }
      }
    }

    /**
     * 点击选框
     * @param item
     */
    function handleCheckChange(item) {
      const { childrenKeys, parentKeys, checkedStatus, isLeaf, disabled = false } = item
      if (!props.showCheckbox) return
      if (disabled) return

      // 当前
      item.checkedStatus = checkedStatus === isCheckedStatus ? unCheckedStatus : isCheckedStatus

      // 子类
      if (!props.checkStrictly) {
        if (props.expandChecked) {
          item.show = true
          item.expand = childrenKeys?.length > 0 || isLeaf
        }

        childrenKeys.forEach(k => {
          const childrenItem = unref(datamap)[k]
          childrenItem.checkedStatus = childrenItem.disabled ? childrenItem.checkedStatus : item.checkedStatus

          if (props.expandChecked) {
            childrenItem.show = true
            childrenItem.expand = childrenItem?.childrenKeys?.length > 0 || childrenItem.isLeaf
          }
        })
      } else {
        if (props.expandChecked) {
          logError(`多选时，当 checkStrictly 为 true 时，不支持选择自动展开子节点属性(expandChecked)`)
        }
      }

      // 父类
      if (!props.checkStrictly) {
        parentKeys.forEach(k => {
          const parentItem = datamap.value[k]
          parentItem.checkedStatus = getParentCheckedStatus(parentItem)
        })
      }

      const hasCheckedKeys = []
      for (let i = 0; i < datalist.value.length; i++) {
        const k = datalist.value[i]
        if (k.checkedStatus === isCheckedStatus) {
          if ((props.packDisabledkey && k.disabled) || !k.disabled) {
            hasCheckedKeys.push(k.key)
          }
        }
      }

      checkedKeys.value = [...hasCheckedKeys]

      emit('change', hasCheckedKeys, item)
    }

    /**
     * 点击单选
     * @param item
     */
    function handleRadioChange(item) {
      const { parentKeys, checkedStatus, key, disabled = false, isLeaf } = item
      if (props.showCheckbox) return
      if (props.onlyRadioLeaf && !isLeaf) handleExpandedChange(item)

      if (disabled) return

      // 重置所有选择
      if (datalist.value?.length) {
        for (let i = 0; i < datalist.value.length; i++) {
          const k = datalist.value[i]
          k.checkedStatus = unCheckedStatus
        }
      }

      parentKeys.forEach(k => {
        const parentItem = datamap.value[k]
        parentItem.checkedStatus = getParentCheckedStatus(parentItem)
      })

      // 当前
      item.checkedStatus = checkedStatus === isCheckedStatus ? unCheckedStatus : isCheckedStatus

      checkedKeys.value = key
      emit('change', key, item)
    }

    /**
     * 点击标签
     */
    function handleLabelClick(item) {
      if (props.showCheckbox) {
        handleCheckChange(item)
      } else {
        handleRadioChange(item)
      }
    }

    /**
     * 点击展开收起
     * @param item
     */
    async function handleExpandedChange(item) {
      if (props.filterValue) return

      const { expand, loading = false, disabled } = item
      if (loadLoading.value && loading) return

      checkExpandedChange(item)

      // 异步
      item.expand = !expand

      let currentItem = null
      if (!disabled) {
        if (!props.showCheckbox && props.onlyRadioLeaf && props.loadMode) {
          logError(`单选时，当 onlyRadioLeaf 为 true 时不支持动态数据`)
        } else {
          currentItem = await loadExpandNode(item)
        }
      }

      emit('expand', !expand, currentItem || item || null)
    }

    /**
     * 检查展开状态
     * @param item
     */
    function checkExpandedChange(item) {
      const { expand, childrenKeys, children = null } = item

      if (expand) {
        if (childrenKeys?.length) {
          childrenKeys.forEach(k => {
            if (unref(datamap)[k]) {
              unref(datamap)[k].show = false
              unref(datamap)[k].expand = false
            }
          })
        }
      } else {
        if (children?.length) {
          const childrenKeys = children.map(k => k.key)
          childrenKeys.forEach(k => {
            if (unref(datamap)[k]) {
              unref(datamap)[k].show = true
            }
          })
        }
      }
    }

    /**
     * 加载异步数据
     * @param item
     */
    async function loadExpandNode(item) {
      const { expand, key, loaded, children } = item
      if (children?.length && !props.alwaysFirstLoad) {
        return item
      }

      if (expand && props.loadMode && !loaded) {
        if (isFunction(props.loadApi)) {
          expandedKeys.value.push(key)
          loadLoading.value = true
          item.loading = true

          const currentNode = deepClone(item)
          const apiRes = await props.loadApi(currentNode)

          // 新增子项
          let newChildren = [...(item.originItem?.children || []), ...(apiRes || [])]
          const newChildrenObj = {}
          newChildren = newChildren.reduce((total, next) => {
            newChildrenObj[next[fieldMap.value]] ? '' : newChildrenObj[next[fieldMap.value]] = true && total.push(next)
            return total
          }, [])

          item.originItem.children = newChildren || null
          if (apiRes?.length) {
            const insertIndex = datalist.value.findIndex(k => k.key === item.key)
            handleTreeData(apiRes, item, item.level + 1, insertIndex)
            datalist.value = checkInitData(datalist.value)
          } else {
            // 加载后无数据就移除展开图标
            item.expand = false
            item.isLeaf = true
            item.showArrow = false
          }

          loadLoading.value = false
          item.loading = false
          item.loaded = true
        }
      } else {
        const eki = expandedKeys.value.findIndex(k => k === key)
        if (eki >= 0) {
          expandedKeys.value.splice(eki, 1)
        }
      }

      return item
    }

    /**
     * 获取父类的选中状态
     * @param item
     */
    function getParentCheckedStatus(item) {
      if (!item) {
        return unCheckedStatus
      }

      if (!props.checkedDisabled && item.disabled) {
        return item.checkedStatus || unCheckedStatus
      }

      // 单选时，父类永远为半选
      if (!props.showCheckbox) {
        return halfCheckedStatus
      }

      const { children } = item
      // 子类全选中
      const childrenCheckedAll = children.every(k => k.checkedStatus === isCheckedStatus)
      if (childrenCheckedAll) {
        return isCheckedStatus
      }

      // 子类全不选中
      const childrenUncheckedAll = children.every(k => k.checkedStatus === unCheckedStatus)
      if (childrenUncheckedAll) {
        return unCheckedStatus
      }

      return halfCheckedStatus
    }

    function filterData() {
      if (props.filterValue === '') {
        datalist.value.forEach(k => {
          k.show = true
        })
        return
      }

      datalist.value.forEach(k => {
        if (k.label.indexOf(props.filterValue) > -1) {
          k.show = true
          k.parentKeys.forEach(k => {
            datamap.value[k].show = true
          })
        } else {
          k.show = false
        }
      })

      datalist.value.forEach(k => {
        if (k.show) {
          k.parentKeys.forEach(k => {
            datamap.value[k].show = true
          })
        }
      })
    }

    /**
     * 返回已选的 key
     */
    const getCheckedKeys = () => getAllNodeKeys(datalist.value, 'checkedStatus', isCheckedStatus, props.packDisabledkey)
    /**
     * 根据key设置已选
     * @param keys 单选时为数字或者字符串，多选时为数组
     * @param checked 多选时为key的数组，单选时为key
     */
    function setCheckedKeys(keys, checked = true) {
      // 多选
      if (props.showCheckbox) {
        if (!isArray(keys)) {
          logError(`setCheckedKeys 第一个参数非数组，传入的是[${keys}]`)
          return
        }

        const list = datalist.value

        // 取消选择
        if (checked === false) {
          let newCheckedKeys = []
          for (let i = 0; i < checkedKeys.value.length; i++) {
            const ck = checkedKeys.value[i]
            if (!keys.includes(ck)) {
              newCheckedKeys.push(ck)
            }
          }
          newCheckedKeys = [...new Set(newCheckedKeys)]
          checkedKeys.value = newCheckedKeys
          handleCheckState(list, keys, false)

          return
        }

        // 选择
        const newCheckedKeys = [...checkedKeys.value, ...keys]
        checkedKeys.value = [...new Set(newCheckedKeys)]
        handleCheckState(list, checkedKeys.value, true)

        if (props.expandChecked && checked) {
          expandedKeys.value = [...new Set([...(checkedKeys.value || []), ...(keys || [])])]
          handleExpandState(list, keys, true)
        }
        return
      }

      // 单选
      // 如果为数组则拿第一个
      if (isArray(keys)) {
        keys = keys[0]
      }

      if (!isString(keys) && !isNumber(keys)) {
        logError('setCheckedKeys 第一个参数字符串或数字，传入的是==>', keys)
        return
      }

      const list = datalist.value
      checkedKeys.value = checked ? keys : null

      if (props.expandChecked && checked) {
        handleExpandState(list, [keys], true)
      }

      handleCheckState(list, keys, !!checked)
    }
    /**
     * 返回半选的 key
     */
    const getHalfCheckedKeys = () => getAllNodeKeys(datalist.value, 'checkedStatus', halfCheckedStatus, props.packDisabledkey)
    /**
     * 返回未选的 key
     */
    const getUncheckedKeys = () => getAllNodeKeys(datalist.value, 'checkedStatus', unCheckedStatus, props.packDisabledkey)
    /**
     * 返回已展开的 key
     */
    const getExpandedKeys = () => getAllNodeKeys(datalist.value, 'expand', true)
    /**
     * 返回未展开的 key
     */
    const getUnexpandedKeys = () => getAllNodeKeys(datalist.value, 'expand', false)
    /**
     * 根据key展开/收起
     *
     * @param keys 数组，或字符串 all
     * @param expand true为展开/false为收起
     */
    function setExpandedKeys(keys, expand = true) {
      if (!Array.isArray(keys) && keys !== 'all') {
        logError('setExpandedKeys 第一个参数非数组，传入的是===>', keys)
        return
      }

      const list = datalist.value

      // 展开/收起全部
      if (keys === 'all') {
        list.forEach(k => {
          k.expand = expand
          if (k.level > 0) {
            k.show = expand
          }
        })
        return
      }

      // 收起
      if (expand === false) {
        const newExpandedKeys = []
        for (let i = 0; i < expandedKeys.value.length; i++) {
          const ek = expandedKeys.value[i]
          if (!keys.includes(ek)) {
            newExpandedKeys.push(ek)
          }
        }
        expandedKeys.value = [...new Set(newExpandedKeys)]
        handleExpandState(list, keys, false)

        return
      }

      // 展开
      const newExpandedKeys = []
      for (let i = 0; i < list.length; i++) {
        if (keys.includes(list[i].key)) {
          newExpandedKeys.push(list[i].key)
        }
      }
      expandedKeys.value = [...new Set(newExpandedKeys)]
      handleExpandState(list, newExpandedKeys, true)
    }
    /**
     * 返回已选的节点
     */
    const getCheckedNodes = () => getAllNodes(datalist.value, 'checkedStatus', isCheckedStatus, props.packDisabledkey)
    /**
     * 返回半选的节点
     */
    const getHalfCheckedNodes = () => getAllNodes(datalist.value, 'checkedStatus', halfCheckedStatus, props.packDisabledkey)
    /**
     * 返回未选的节点
     */
    const getUncheckedNodes = () => getAllNodes(datalist.value, 'checkedStatus', unCheckedStatus, props.packDisabledkey)
    /**
     * 返回已展开的节点
     */
    const getExpandedNodes = () => getAllNodes(datalist.value, 'expand', true)
    /**
     * 返回未展开的节点
     */
    const getUnexpandedNodes = () => getAllNodes(datalist.value, 'expand', false)

    watch(
      () => props.defaultExpandedKeys,
      (v) => {
        if (v?.length) {
          expandedKeys.value = v
        } else {
          expandedKeys.value = []
        }

        // if (v) checkInitData(datalist.value)
      },
      { immediate: true }
    )

    watch(
      () => props.defaultCheckedKeys,
      (v) => {
        if (props.showCheckbox) {
          if (v?.length) {
            checkedKeys.value = v
          } else {
            checkedKeys.value = []
          }
        } else {
          if (v || v === 0) {
            checkedKeys.value = v
          } else {
            checkedKeys.value = null
          }
        }
        // checkInitData(datalist.value)
      },
      { immediate: true }
    )

    watch(
      () => props.data,
      (v) => {
        dataRef.value = deepClone(v)
        setTimeout(() => {
          initData()
        }, 36)
      },
      { immediate: true, deep: true }
    )

    watch(
      () => props.filterValue,
      () => {
        filterData()
      },
    )

    return {
      datalist,
      unCheckedStatus,
      halfCheckedStatus,
      isCheckedStatus,
      handleCheckChange,
      handleRadioChange,
      handleLabelClick,
      handleExpandedChange,
      loadLoading,

      // updateChildrenByKey: () => {},
      // insertBeforeByKey: () => {},
      // insertAfterByKey: () => {},
      getCheckedKeys,
      setCheckedKeys,
      getHalfCheckedKeys,
      getUncheckedKeys,
      getExpandedKeys,
      getUnexpandedKeys,
      setExpandedKeys,
      getCheckedNodes,
      getHalfCheckedNodes,
      getUncheckedNodes,
      getExpandedNodes,
      getUnexpandedNodes,
    }
  },
})
</script>

<style lang="scss" scoped>
@font-face {
  font-family: 'da-tree-iconfont'; /* Project id  */
  src: url('data:application/octet-stream;base64,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') format('truetype');
}

.da-tree {
  width: 100%;
  height: 100%;

  &-scroll {
    width: 100%;
    height: 100%;
  }

  &-item {
    display: flex;
    align-items: center;
    height: 0;
    padding: 0;
    overflow: hidden;
    font-size: 28rpx;
    line-height: 1;
    visibility: hidden;
    opacity: 0;
    transition: opacity 0.2s linear;

    &.is-show {
      height: auto;
      padding: 12rpx 24rpx;
      visibility: visible;
      opacity: 1;
    }

    &__icon {
      display: flex;
      align-items: center;
      justify-content: center;
      width: 40rpx;
      height: 40rpx;
      overflow: hidden;

      &--arr {
        position: relative;
        display: flex;
        align-items: center;
        justify-content: center;
        width: 32rpx;
        height: 32rpx;

        &::after {
          position: relative;
          z-index: 1;
          overflow: hidden;
          /* stylelint-disable-next-line font-family-no-missing-generic-family-keyword */
          font-family: 'da-tree-iconfont' !important;
          font-size: 32rpx;
          font-style: normal;
          color: #999;
          -webkit-font-smoothing: antialiased;
          -moz-osx-font-smoothing: grayscale;
        }

        &.is-expand {
          &::after {
            content: '\e604';
          }
        }

        &.is-right {
          transform: rotate(-90deg);
        }

        &.is-loading {
          animation: IconLoading 1s linear 0s infinite;

          &::after {
            content: '\e7f1';
          }
        }
      }
    }

    &__checkbox {
      width: 40rpx;
      height: 40rpx;
      overflow: hidden;

      &--left {
        order: 0;
      }

      &--right {
        order: 1;
      }

      &--icon {
        position: relative;
        display: flex;
        align-items: center;
        justify-content: center;
        width: 40rpx;
        height: 40rpx;

        &::after {
          position: relative;
          top: 0;
          left: 0;
          z-index: 1;
          overflow: hidden;
          /* stylelint-disable-next-line font-family-no-missing-generic-family-keyword */
          font-family: 'da-tree-iconfont' !important;
          font-size: 32rpx;
          font-style: normal;
          -webkit-font-smoothing: antialiased;
          -moz-osx-font-smoothing: grayscale;
        }

        &.da-tree-checkbox-outline::after {
          color: #bbb;
          content: '\ead5';
        }

        &.da-tree-checkbox-checked::after {
          color: var(--theme-color,#007aff);
          content: '\ead4';
        }

        &.da-tree-checkbox-indeterminate::after {
          color: var(--theme-color,#007aff);
          content: '\ebce';
        }

        &.da-tree-radio-outline::after {
          color: #bbb;
          content: '\ecc5';
        }

        &.da-tree-radio-checked::after {
          color: var(--theme-color,#007aff);
          content: '\ecc4';
        }

        &.da-tree-radio-indeterminate::after {
          color: var(--theme-color,#007aff);
          content: '\ea4f';
        }
      }

      &.is--disabled {
        cursor: not-allowed;
        opacity: 0.35;
      }
    }

    &__label {
      flex: 1;
      margin-left: 4rpx;
      color: #555;

      &--2 {
        color: var(--theme-color,#007aff);
      }

      &--append {
        font-size: 60%;
        opacity: 0.6;
      }
    }
  }
}

@keyframes IconLoading {
  0% {
    transform: rotate(0deg);
  }

  100% {
    transform: rotate(360deg);
  }
}
</style>
